home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / progjour / 1991 / 02 / ems.asm < prev    next >
Assembly Source File  |  1990-10-31  |  7KB  |  367 lines

  1.     title    expanded memory interace
  2.     include    asm.inc
  3.  
  4.     public    ems_exchange
  5.     public    ems_in
  6.     public    ems_out
  7.  
  8. EMS_MAX            equ    1024    ; (must be multiple of 8)
  9. NULL_EMS        equ    0
  10.  
  11. move_source_dest_struct    struc    ; from "official" LIM EMS 4.0 Spec - page 3-87
  12.   region_length            dd ?
  13.   source_memory_type        db ?
  14.   source_handle            dw ?
  15.   source_initial_offset        dw ?
  16.   source_initial_seg_page    dw ?
  17.   dest_memory_type        db ?
  18.   dest_handle            dw ?
  19.   dest_initial_offset        dw ?
  20.   dest_initial_seg_page        dw ?
  21. move_source_dest_struct    ends
  22.  
  23.  
  24. XIB    segment word public 'DATA'    ; enable exit intercept during
  25. XIB    ends                ;  intialization
  26. XI    segment word public 'DATA'
  27.     dw    enable_exit_intercept
  28. XI    ends
  29. XIE    segment word public 'DATA'
  30. XIE    ends
  31.  
  32. XCB    segment word public 'DATA'    ; always release EMS on termination
  33. XCB    ends
  34. XC    segment word public 'DATA'
  35.     dw    ems_close
  36. XC    ends
  37. XCE    segment word public 'DATA'
  38. XCE    ends
  39.  
  40.  
  41.     .data?
  42. ems_struc    move_source_dest_struct <>
  43.  
  44. ems_count    dw    ?        ; number of allocated pages
  45. ems_handle    dw    ?
  46.  
  47. ems_ecount    dw    ?
  48. ems_icount    dw    ?
  49. ems_ocount    dw    ?
  50.  
  51. ems_version    db    ?
  52. ems_flag    db    ?
  53.  
  54. ems_bits    db    EMS_MAX/8 dup(?)
  55.  
  56.  
  57.     .const
  58. ertx_ems_index    db    'Bad EMS index',0
  59. ertx_ems_error    db    'Error in EMS',0
  60.  
  61.  
  62.     .code
  63.     extn    set_strerror,get_vector,enable_exit_intercept
  64.  
  65.  
  66. ;;    do ems function
  67. ;
  68. ;    exit    Cf    if error (sets error string)
  69. ;
  70. do_ems_function proc
  71.     int    67h
  72.     or    ah,ah
  73.     jnz    def1            ;  if EMS error
  74.     ret
  75.  
  76. def1:    lea    ax,ertx_ems_error    ; *Error in EMS*
  77.     jmp    set_strerror
  78. do_ems_function endp
  79.  
  80.  
  81. ;;    do ems raw
  82. ;
  83. ;    exit    Cf    if error (doesn't set error string)
  84. ;
  85. do_ems_raw proc
  86.     int    67h
  87.     or    ah,ah
  88.     jnz    der1            ;  if EMS error
  89.     ret
  90. der1:    stc
  91.     ret
  92. do_ems_raw endp
  93.  
  94.  
  95. ;;    ems close
  96. ;
  97. ;    uses    AX,DX
  98. ;
  99. ems_close proc
  100.     movx    dx,NULL_EMS
  101.     xchg    dx,ems_handle[bp]
  102.     cmpx    dx,NULL_EMS
  103.     je    ecl1            ;\ if EMS not in use
  104.  
  105.     mov    ah,45h            ; deallocate pages
  106.     call    do_ems_function
  107. ecl1:    ret
  108. ems_close endp
  109.  
  110.  
  111. ;;    ems exchange
  112. ;
  113. ;    entry    AX    page index (1..n)
  114. ;        ES:DI    destination
  115. ;    exit    Cf    if bad block or EMS error
  116. ;    uses    AX
  117. ;
  118. ems_exchange proc
  119.     pushm    si,ds            ; adjust and set EMS page index
  120.     dec    ax
  121.     mov    ems_struc.dest_initial_seg_page[bp],ax
  122.  
  123.     call    read_move_struc
  124.     jc    eex1            ;  if no EMS
  125.     mov    dest_handle[si],ax
  126.  
  127.     movx    ax,0            ; fill in move structure
  128.     mov    source_memory_type[si],al
  129.     mov    source_handle[si],ax
  130.     mov    source_initial_offset[si],di
  131.     mov    source_initial_seg_page[si],es
  132.     mov    dest_memory_type[si],1
  133.     mov    dest_initial_offset[si],ax
  134.  
  135.     mov    ax,5701h        ; exchange RAM and EMS
  136.     call    do_ems_function
  137.     inc    ems_ecount[bp]
  138.  
  139. eex1:    popm    ds,si
  140.     ret
  141. ems_exchange endp
  142.  
  143.  
  144. ;;    ems in
  145. ;
  146. ;    entry    AX    block index (1..n)
  147. ;        ES:DI    destination (no transfer if NULL)
  148. ;    exit    Cf    if bad block or EMS error
  149. ;    uses    AX
  150. ;
  151. ems_in proc
  152.     pushm    cx,si,ds
  153.     dec    ax            ; clear index bit
  154.     js    ein2            ;  if bad swap index (cannot be -)
  155.     mov    si,ax
  156.     mov    cl,3            ;  (divide bit number by 8 to select
  157.     shr    si,cl            ;   byte)
  158.  
  159.     mov    cl,al            ;  (use the 3 least significant bits
  160.     and    cl,7            ;   to rotate a mask)
  161.     mov    ch,10000000b
  162.     ror    ch,cl
  163.     test    ems_bits[bp+si],ch
  164.     jz    ein2            ;  if bad EMS index
  165.     xor    ems_bits[bp+si],ch    ;  (Cf=0)
  166.  
  167.     mov    cx,es            ; do not read EMS file if NULL output
  168.     jcxz    ein1            ;  if NULL destination (Cf==0)
  169.  
  170.                     ; set structure for move memory region
  171.     mov    ems_struc.source_initial_seg_page[bp],ax
  172.  
  173.     call    read_move_struc
  174.     jc    ein1            ;  if no EMS
  175.     mov    source_handle[si],ax
  176.  
  177.     movx    ax,0
  178.     mov    source_memory_type[si],1
  179.     mov    source_initial_offset[si],ax
  180.     mov    dest_memory_type[si],al
  181.     mov    dest_handle[si],ax
  182.     mov    dest_initial_offset[si],di
  183.     mov    dest_initial_seg_page[si],es
  184.  
  185.     mov    ax,5700h        ; move from EMS to RAM
  186.     call    do_ems_function
  187.     inc    ems_icount[bp]
  188.  
  189. ein1:    popm    ds,si,cx
  190.     ret
  191.  
  192. ein2:    lea    ax,ertx_ems_index    ; *Bad EMS index*
  193.     call    set_strerror
  194.     jmp    ein1
  195. ems_in endp
  196.  
  197.  
  198. ;;    ems out
  199. ;
  200. ;    entry    ES:DI    source
  201. ;    exit    AX    block index (1..n)
  202. ;        Cf    if EMS full or EMS error
  203. ;
  204. ems_out proc
  205.     pushm    cx,si,ds
  206.     call    read_move_struc        ; set structure for move memory region
  207.     jc    eou2            ;  if no EMS
  208.     mov    dest_handle[si],ax
  209.  
  210.     movx    ax,0
  211.     mov    source_memory_type[si],al
  212.     mov    source_handle[si],ax
  213.     mov    source_initial_offset[si],di
  214.     mov    source_initial_seg_page[si],es
  215.     mov    dest_memory_type[si],1
  216.     mov    dest_initial_offset[si],ax
  217.  
  218.     call    get_ems_index        ; select next free EMS block
  219.     jc    eou2            ;  if EMS bit map full
  220.     mov    dest_initial_seg_page[si],ax
  221.     mov    cx,ax
  222.  
  223.     cmp    ax,ems_count[bp]    ; check EMS allocation
  224.     jb    eou1            ;  if enough EMS pages allocated
  225.     call    realloc_more_ems    ;  else get more ESM from driver
  226.     jc    eou2            ;   if EMS full
  227.  
  228. eou1:    mov    ax,5700h        ; move from EMS to RAM
  229.     call    do_ems_function
  230.     inc    ems_ocount[bp]
  231.  
  232.     mov    ax,cx            ;  return EMS index (1..MAX)
  233.     inc    ax
  234.  
  235. eou2:    popm    ds,si,cx
  236.     ret
  237. ems_out endp
  238.  
  239.  
  240. ;;    get ems index
  241. ;
  242. ;    exit    AX    ems index (0..MAX-1)
  243. ;        Cf    if no (more) EMS
  244. ;    uses    CX
  245. ;
  246. get_ems_index proc
  247.     push    si
  248.     mov    al,1
  249.     mov    cx,EMS_MAX
  250.     lea    si,ems_bits-1
  251.  
  252.     even                ; search ems bits for first free index
  253. gei1:    ror    al,1
  254.     adc    si,ZER0
  255.     test    al,[bp+si]
  256.     loopnz    gei1
  257.     stc
  258.     jnz    gei2            ; if EMS full
  259.     or    [bp+si],al
  260.  
  261.     mov    ax,EMS_MAX-1
  262.     sub    ax,cx
  263.  
  264. gei2:    pop    si
  265.     ret
  266. get_ems_index endp
  267.  
  268.  
  269. ;;    get ems version
  270. ;
  271. ;    exit    AL    EMS version or 0 if no EMS
  272. ;    uses    SI,DS
  273. ;
  274. get_ems_version proc
  275.     mov    al,67h
  276.     call    get_vector
  277.     mov    si,0Ah
  278.     lodsw
  279.     cmp    ax,'ME'
  280.     jne    gev1            ; if no EMS
  281.     lodsw
  282.     cmp    ax,'XM'
  283.     jne    gev1            ; if no EMS
  284.     lodsw
  285.     cmp    ax,'XX'
  286.     jne    gev1            ; if no EMS
  287.     lodsw
  288.     cmp    ax,'0X'
  289.     jne    gev1            ; if no EMS
  290.  
  291.     mov    ah,46h            ; get EMS version
  292.     call    do_ems_function
  293.     jnc    gev2
  294.  
  295. gev1:    movx    ax,0
  296.     stc
  297. gev2:    ret
  298. get_ems_version endp
  299.  
  300.  
  301. ;;    read move struc
  302. ;
  303. ;    exit    AX    EMS handle
  304. ;        DS:SI    "move source dest" structure
  305. ;        Cf    if no EMS
  306. ;    note    all members set to zero except region_length
  307. ;
  308. read_move_struc proc
  309.     mov    ax,ems_handle[bp]
  310.     cmpx    ax,NULL_EMS
  311.     je    rms2            ;  if no ems
  312.  
  313. rms1:    movx    ds,DGROUP_SEGMENT
  314.     lea    si,ems_struc
  315.     mov    wptr region_length[si],BLOCK_SIZE
  316.     mov    wptr region_length[si+2],ZER0
  317.     clc
  318.     ret
  319.  
  320. rms2:    mov    al,-1
  321.     xchg    al,ems_flag[bp]
  322.     add    al,-1
  323.     jc    rms4            ;  if previous attempt failed
  324.  
  325.     call    get_ems_version
  326.     mov    ems_version[bp],al
  327.     cmp    al,40h
  328.     jb    rms4            ;  if EMS missing or out of date
  329.  
  330. rms3:    mov    ah,43h            ; get EMS handle
  331.     pushm    bx,dx
  332.     mov    bx,1            ;  allocate just 1 page
  333.     call    do_ems_raw
  334.     mov    ax,dx
  335.     popm    dx,bx
  336.     jc    rms4            ;  if no EMS available (probably)
  337.     mov    ems_handle[bp],ax
  338.     mov    ems_count[bp],1
  339.  
  340.     cmpx    ax,NULL_EMS        ; reject a zero EMS handle (Cf=0)
  341.     je    rms3            ;  if bad handle
  342.     jmp    rms1
  343.  
  344. rms4:    ret
  345. read_move_struc endp
  346.  
  347.  
  348. ;;    realloc more ems
  349. ;
  350. ;    exit    Cf    if no more EMS
  351. ;    uses    AX
  352. ;
  353. realloc_more_ems proc
  354.     pushm    bx,dx
  355.     mov    bx,ems_count[bp]
  356.     inc    bx
  357.     mov    dx,ems_handle[bp]
  358.     mov    ah,51h
  359.     call    do_ems_raw
  360.     jc    rme1            ; if out of EMS
  361.     mov    ems_count[bp],bx
  362. rme1:    popm    dx,bx
  363.     ret
  364. realloc_more_ems endp
  365.  
  366.     end
  367.